Repository navigation
Upstream sync 11E: AGC driver onto Metal (29 commits) - #512
Conversation
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e50cf05454
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| auto amount = count; | ||
| if (ordered) { | ||
| amount = state.module.AllocateId(); | ||
| state.module.AddFunction(spv::OpGroupNonUniformShuffle, TypeU32(state), amount, ConstantU32(state, spv::ScopeSubgroup), ctx.Arg(inst, 4), EmitHostSubgroupLane(state, sourceLane)); |
There was a problem hiding this comment.
Shuffle the ordered amount across both wave64 halves
For a wave64 ds_ordered_count where lanes 0–31 are inactive and the first active lane is in the upper half, first identifies that upper lane but sourceLane masks it to 0–31 and the shuffle reads ctx.Arg(inst, 4) from the lower-half context. Because the second half returns before this code, the atomic increment uses the inactive lower counterpart's value instead of the first active lane's amount, corrupting the GDS counter when those values differ. Use the paired-half-aware shuffle path (such as ctx.Shuffle(inst, 4, first)) rather than shuffling only the current half.
Useful? React with 👍 / 👎.
A shipping title ends its first run, with no resource plans in the shader cache, with about 4 GB more resident memory than a run with a warm cache. The threads of the registration prepare pool free what they allocate to prepare a shader, but glibc keeps the freed memory in their arenas: at 110 s, 4.6 GB of the 6.5 GB the arenas held was free. When the pool has no task left, the worker that finished last calls malloc_trim, at most once a second, which gives the free pages of every arena back to the system. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit f4f69bb)
…ive COMPUTE_PGM_RSRC1 (cherry picked from commit ee1e341)
(cherry picked from commit 0b5a4aa)
…locks On a host-imported surface a storage write-back keeps the 64 KiB blocks the CPU wrote since their tracked layer's generation, stores the rest and stamps the stored ranges with MarkWritten. Settling advanced the stored layers' generations past those stamps only when no layer kept a block (or when an adjacent pending surface needed the collect). When one tracked layer kept a block, every other stored layer kept its old generation, so the write-back's own stamps read as CPU writes: the next write-back kept those layers as well and did not store the GPU's newer results over them. A tracked layer is one 64 KiB unit when the surface has block units: tiled (not linear), 64 KiB-aligned base, not thick, with layer and block tracking on. Otherwise it is an array layer (64 KiB-aligned layer slices, layer tracking on) or the whole surface. Settling now collects and advances each stored layer that kept no block; a layer that kept a block keeps its old generation and re-uploads at its next use, as before. When no stored layer advances (nothing stored, or every selected layer kept a block, such as a single tracked layer that kept one), no adjacent pending surface needs the collect and no unit was retiled into the unit shadow, settling still skips the collect, as main did. Units retiled into the unit shadow are now marked at the settle collect's generation also when a block was kept; main marked them at TrackerGeneration() there without collecting. The two differ only for a CPU write to a stored unit made after the keep decision: main left it to a later walk, which made the retiled unit stale so the CPU's bytes won; now the walk stamps it at the marked generation and the stored results win, as they already did when no block was kept. agc_storage_kept_unit_settle uses a 1024x512 RGBA8 surface in 64 KiB tiling (32 block units): it writes one byte of unit 0 from the CPU, stores a red clear, stores a blue clear, and requires units 1-31 to hold blue and unit 0 to keep the CPU's byte after both stores. On main the GPU-mapped direct memory case fails with unit 1 still red. The watched-memory case (host imports off: the write-back that stores through the CPU) passes on main; it guards the kept layer's old generation and fails when settling also advances a layer that kept a block. The test returns 77, naming the reason, when the direct-memory case cannot run: no write watching, no host imports, direct memory not write-watched, or its host import refused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit dc39e05)
…ompared agc_storage_kept_unit_settle checked that the GPU-mapped direct memory was write-watched before it made the host import. On Linux, when host imports resolve write protection and dma-buf imports keep it, the host-pointer import is tried first in a window that does not stay watched, and dma-buf only when it fails (importAllocation in GuestBufferMemory.cpp). Where the host-pointer import of shared memory succeeds, as on Intel's ANV, the import takes the direct memory out of the write watch, so the case ran on the compared path: the upload saves the guest bytes, the first write-back keeps unit 0 by comparison and drops the saved bytes of every unit it selected, and the second write-back has nothing to compare. Before e544993 it stored every unit whole, over the CPU's byte in unit 0, which is the failure reported on Linux; on main it throws (technical debt: results over memory outside the write watch without saved bytes). Neither depends on the settle change. On Windows, importing watched private memory (compared there) reproduces both: on 7e181fc, with or without this branch's Texture.cpp change, the second check fails with that message; on main the second write-back throws. The case now checks the write watch again after the import and returns 77, naming the reason, when the import took the memory out of it. Where the import keeps the memory watched (the Windows alias import, a Linux dma-buf import) it runs as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 7bfeeb9)
…ilable Co-Authored-By: Codex <noreply@openai.com> (cherry picked from commit ca73d0f)
Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit 58b2245)
… locks sceAgcCreateInterpolantMapping resolved the pixel shader's ABI, which takes the process-wide shader preparation lock until the scope ends, and then waited under that lock for the vertex shader's background registration preparation. sceAgcCreatePrimState and sceAgcLinkShaders could wait the same way. Every other shader registration and ABI resolution queued behind that one compile: on a shipping title the lock was held 8 to 10 s of every 10 s, almost all of it waiting for registration preparations, while its loader threads waited 13 to 45 s per 10 s to take it. A preparation scope now names the shaders it resolves and waits for their registration preparations before it can take the lock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 11ef8e6)
…location A storage image whose surface runs past the end of its registered allocation had every write-back dropped as "memory no longer registered". Titles can size a single-level surface's allocation as pitch x height. A tiled mip's 64 KiB blocks are stored row-major, so that size ends inside the last block row, and the bytes after it are the tail of that row: they hold texels with y < height, which the GPU's own store writes into the next allocation. When the allocation ends inside the last block row and registered readable memory continues to the surface's end, the write-back now stores the whole surface, as the GPU does. Padding slots keep their bytes, since the store writes only bytes that changed. A shipping title streams its lightmaps into an 8160x8160 BC3 pool (SW_64KB_S, 2048 block rows) through a 2040x2040 RGBA32UI alias written by compute. The game allocates 2040 rows, so all its write-backs were dropped and the walls sampled leftover memory as speckled noise. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 6ad9372)
…put groups The test recompiled and rebuilt the same program for every group of 32 input pairs. Only the input buffer changes between groups, so compile once per compare, EXEC/VCC capture and float mode (96 programs instead of 768) and dispatch it for each group. On lavapipe the test drops from about 11.5 s to 1.3 s; it is the slowest test of the Linux CI run (14.5 s). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 59235d9)
Pointer-shaped calls match the boykopovar#4808 console probe (success, no writes); selecting table 13 for those values was unsupported. (cherry picked from commit eb1b9ec)
A 16-word compute kernel copies a buffer in 16-byte elements: 64 threads a group, thread t of group g loads elements g*128+t and g*128+64+t from the index-addressed buffer in s[0:3] and stores them at the same indices of s[4:7]. Run as a shader against host imports it costs 11.8 ms of GPU per present in a shipping title's main menu on an RTX 4060. Matched like the existing copy kernel, by its code hash and its descriptors (16-byte stride and no swizzle on both, the same word 3), it becomes one copy through the existing copy HLE path: the elements the kernel stores, min of groups * 128 and the destination's record count, when the source's record count covers them all. APS5_NO_COPY_HLE turns it off with the other kernel. (cherry picked from commit fc24253)
The stream copy kernel is matched by its 16 code words instead of a hash, and the match and its range checks become free functions (MatchesStreamCopyKernel, StreamCopyRange) so a test can reach them. Its loads and stores are format instructions, so the match also requires the descriptor the pattern fill takes: 32_32_32_32_UINT, XYZW selects, no add-tid, out-of-bounds mode 0, type 0. Copy paths are counted in copyPathCounts whether or not APS5_PROFILE_DRAW is set. agc_driver_stream_copy checks the match against every word with a bit flipped, the descriptor and dispatch refusals, the range clamp and refusals, and runs nine dispatches through the driver: four must take the HLE path and copy elements g*128+t and g*128+64+t, five must be refused for their shape and leave the shader's result. (cherry picked from commit fa4fc23)
…-image write-back Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit db1ddb9)
Build packs from EncodeEntry output and check the hit and miss paths, an entry stored under another key, a truncated entry, a damaged index, an out-of-range record, a foreign compiler source version and an unknown format. A child process covers pack discovery on a real disk load, the ANYPS5_NO_PREBUILT_SHADERS opt out and fall-through to the writable cache. ARCHITECTURE.md describes where the prebuilt lookup sits. (cherry picked from commit 93ab137)
…rs it reads Co-Authored-By: Claude <noreply@anthropic.com> (cherry picked from commit 5d9def6)
…e dispatch A captured word that no longer matches a live import or mirror only means the capture raced a guest write; the GPU reads the live bytes either way, as the hardware would. The compare now counts such mismatches and reports them with the snapshot, the region and the first differing offset at most every 10 s instead of throwing; APS5_SNAPSHOT_CHECK_FATAL=1 restores the throw, and a snapshot-backed region still fails, now naming the snapshot, the region and the first differing offset. an Unreal Engine 5 title hit the throw within 65 to 91 s of reaching its title screen. (cherry picked from commit 67973cd)
(cherry picked from commit ea13f6a)
(cherry picked from commit 6e3152f)
Apple clang ships libc++, which differs from libstdc++ where the sources relied on it: - std::atomic<std::shared_ptr<T>> is not provided. AtomicSharedPtr is that type where the library has it and a mutex-guarded pointer with the same member functions elsewhere; the AGC driver uses it. - std::atomic_ref<const T> is not provided; the page span reads go through a non-const reference. - std::filesystem::file_time_type::clock::to_sys is not provided; std::chrono::file_clock::to_sys is. - std::max and std::min do not deduce across the integer types of the guest range arithmetic, which is spelled with an explicit type. - <string> and <initializer_list> are included where the sources and tests use them. (cherry picked from commit facc03a)
…ted memory budget The storage image cache kept a quarter of the device-local heap (4 GiB on a 16 GiB card) regardless of how much of the heap the driver reports as usable. With a desktop and other allocations the reported budget is about 10 GiB, the cache stayed full at 4 GiB, and after minutes of a cutscene device buffer allocations failed with VK_ERROR_OUT_OF_DEVICE_MEMORY. The cache budget is now the smaller of that quarter of the heap and a quarter of the reported budget, at least 512 MiB, read once per second; APS5_TEXTURE_CACHE_MIB still overrides it. The budget report names the storage budget in use. A test covers the limits. (cherry picked from commit 64ffeb8)
…ialize (cherry picked from commit 9960503)
…er and V# (cherry picked from commit 7af2961)
(cherry picked from commit d16745b)
(cherry picked from commit 843f7e9)
With one sample, PA_SC_AA_MASK leaves one coverage bit per pixel of the 2x2 quad, so a draw can cover only some pixels of every quad (a shipping title renders a target one quarter of the pixels at a time this way). The pixel stage info carries that 4-bit mask; a fragment shader whose mask is not full starts by killing the invocation unless its gl_FragCoord quad position is covered, and runs without early fragment tests. The mask is part of the recompile cache key and the serialized request (fork request version 26). Sample masks of multisampled draws stay refused. (cherry picked from commit 72518f6)
11ef8e6 passes the stages a preparation scope covers to AgcDriverBeginShaderPreparation_nid_postfix, so the Vulkan driver can settle their queued preparations. The Metal build's empty stub takes the same arguments and still keeps no prepared state. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj
With PA_SC_AA_MASK covering only some pixels of a quad, the uncovered pixels run on the hardware as helper lanes, so derivatives of the covered pixels stay defined. OpKill ends those invocations; OpDemoteToHelperInvocation keeps them as helpers. The device enables VK_EXT_shader_demote_to_helper_invocation when available and passes the DemoteToHelperInvocation capability and its SPIR-V extension to the recompiler target and the graphics shader validation. A demoted pixel also reads as a helper, so its initial EXEC bit is clear as on the hardware. Without demote, OpKill stays for pixel programs that read no neighbouring lanes; implicit-LOD sampling, LOD queries and cross-lane reads are refused. The quad pixel mask execution test now also samples a mipmapped texture with implicit LOD under the mask. (cherry picked from commit 90b20af)
…ask without demote A program that enables whole-quad mode (s_wqm_b64) and then reads a ballot or readfirstlane sees the helper lanes, which OpKill removes. (cherry picked from commit 90783f2)
ReadFirstLane, Ballot and PermuteU32 can consume uncovered helper lanes after a fragment explicitly enables EXEC. Classify those operations as neighbour reads so a partial quad mask refuses their kill fallback when demote is unavailable. ReadFirstLane also stays protected when a constant whole-quad instruction folds away. The CPU regression covers explicit EXEC, constant WQM, a comparison ballot and ds_permute. Unmasked programs still compile, supported masked programs retain demote and their subgroup operation, and constant colour keeps the kill fallback. The recovered source fails the readfirstlane and ballot checks; the corrected source passes both the focused check and shader-memory suite. Co-Authored-By: Codex <noreply@openai.com> (cherry picked from commit dbbe282)
72518f6 reads PA_SC_AA_MASK (0x30e, 0x30f) when it decodes the pixel stage, for the quad pixel mask. The Metal render-state test built its registers without them, so the decode threw. The fixture now sets both masks to cover every sample, as CLEAR_STATE does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj
e50cf05 to
1ca8a79
Compare
Upstream sync 11, slice E: AGC driver onto Metal. Range
63fb0cd92..upstream/main(headd92a8dad3), areaagc(124 listed commits), plus the four shader-recompiler commits #511 left for this slice. It was built on #511, whose request-serializer numbering it extends (fork version 25), and was rebased onto main after #511 and #507 merged. Both rebases were clean, and the tree is unchanged from the tested pre-rebase tip. 29 upstream commits are cherry-picked with-x, one each (28 from the AGC list, 1 shader leftover). Two fork commits follow (one forced by a shared API change, one test fixture). Six commit messages were reworded because they named a title or a title ID (f4f69bb71,11ef8e6c8,fc2425348,67973cd89,6ad9372fd,72518f64f); the title is now "a shipping title" / "an Unreal Engine 5 title". One added debt line (d16745be1) had a title ID replaced by "one title", and the sceAgcInit debt line ported fromeb1b9eca9leaves out two homebrew title IDs.Versions: the recompile-request serializer goes from fork version 25 to fork version 26 (adds
quadPixelMask, written after the fork'slayerBase). Upstream numbers this field 28. Upstream's second bump (29, quad sample masks) belongs to1ffc5f672, which is skipped, so there is no fork 27.ShaderDiskCache::FormatVersionstays 37: the stencil-replay series that changes the cache payload is skipped (see below).Metal backend files:
MetalDriver.mm,MetalDraw.mm,MetalPacketExecution.mmandMetalTexture*are untouched. One Metal-side file changed:Graphics/Metal/MetalHostExports.cpp(fork commit3dc0eea15), because11ef8e6c8changed the signature ofAgcDriverBeginShaderPreparation_nid_postfix. The empty Metal stub now takes the stage list and still does nothing.Ported
On the Metal/Rosetta path (shared
State.cpp,ShaderInputState.cpp, libSceAgc, libc, or the shader recompiler):72518f64fsingle-sample sample masks as a per-quad-pixel discard. Shared decode now acceptsPA_SC_AA_MASKon single-sample draws, and the pixel stage info carries the 4-bit quad mask. The recompiler kills uncovered quad pixels; on Metal that reaches MSL through the SPIR-V bridge. Conflicts: the fork's serializer layout (layerBaseat v24, linked-call fallbacks at v25) is kept, and the mask is read at v26. TheShaderMemorytest moves its fixtures to 26/27, and the legacy replays check the default mask 0xf. The message no longer names a title, and its version note says fork 26.90b20afacdemote quad-mask pixels to helpers. The recompiler emitsOpDemoteToHelperInvocationonly when the target lists that capability. The Metal driver's target does not, so on Metal a partial quad mask keepsOpKill, and a pixel program that reads neighbour lanes under one is refused with a named reason. Enabling demote on Metal (MSL 2.3) is left for a Metal-side PR. Vulkan side: the fork'sValidateShaders/Inspectgain only the demote flag, not upstream's clip/cull/viewport-layer/descriptor-array flags.90783f274(shader-slice leftover) whole-quad mode counts as a neighbour-lane read.dbbe282c1ReadFirstLane/Ballot/Permute count too, and the new ShaderMemory test is registered.843f7e963skip unused pixel stages with retained export formats.PixelProgramSkippedis used by the sharedDrawDispatch.cppon Metal. Test conflicts: only this commit's tests were added.ee1e34197an unregistered compute shader takes its float mode from the live COMPUTE_PGM_RSRC1.DispatchFloatModeis built on the fork's sharedFloatModeRegisterFor/DecodeFloatModeinstead of upstream's switch, and the fork's wave-size decode is kept.11ef8e6c8settle registration preparations before a preparation scope locks (libSceAgc call sites plus the Vulkan registry; see the fork stub above).eb1b9eca9sceAgcInit returns 0 for versions >= 14 without a table lookup.9d412df7band4832bd825were already on main. The debt line goes intoTechnicalDebt.md(main has nodebt/libSceAgc.md).facc03ae9build with libc++ (AtomicSharedPtr, libcGuestAllocations, SaveData file clock).93ab13719prebuilt shader pack loading tests (followsf31deebcdfrom Upstream sync 11D: shader recompiler (13 commits) #511). Conflict: only this commit's tests were added, beside main's plan round-trip test.58b224502(type-0 descriptors; the behaviour was already on main),5d9def64e(COPY_DATA from a register; the code was already on main),d16745be1(accepted VGT_SHADER_STAGES_EN).Vulkan driver side, carried to stay close to upstream (not built on macOS):
f4f69bb71return freed memory when shader preparation drains (keeps the fork'sstd::functiontask queue)0b5a4aae3store small pending storage results at each flip (header: declarations from unported neighbours dropped)dc39e051b,7bfeeb977,ca73d0fb3write-back layer advance and settle tests;6ad9372fdoverhanging last block row59235d9cbv_cmp denormals test compiles oncefc2425348,fa4fc2347stream copy kernel HLE and testsdb1ddb96cadjacent registered allocations cover a write-back (test: this commit's case only)67973cd89a live-backed snapshot mismatch no longer fails the dispatchea13f6a4b,6e3152f0eprint the first worker failure. OnlyPrintFailureis added, because the fork'sLifecycle.cpphas no import-stack helpers. The test list drops upstream's present-mode test, which main lacks.64ffeb8c9size the storage image cache from the device memory budget9960503f6,7af296130name the shader when a draw stage fails (the fork keeps nostageCapture.capture)Skipped
cac135528(fix(shader): honor disabled optimization during specialization boykopovar/AnyPS5#4827 test),c280018b0(type-0 descriptors),9d412df7b,4832bd825(sceAgcInit clamp),5409226dd(COPY_DATA register source andNoteDispatchRegisters, whichMetalPacketExecutionalready calls),632331d1a(vertex stage state),f1c786de2(upstream PRs: BDA and memory emission in the shader output (U2) #473),f8e8aca5c(fractional-even tessellation; the rest needs feat(agc): rebuild the hull's relative patch index when it is used as data boykopovar/AnyPS5#4201 quad domains), and perf(graphics): retain vertex input layouts boykopovar/AnyPS5#1316 vertex input layoutsc724c6932,1efbb8714,02e58e993,7a12992d9(adapted to Metal in U3, Upstream PR batch 1 U3: recompiler front-end cache and per-draw CPU #474).c9ba43bfb,4e27d8d75. Windows only:445db4d01,d0823dd4f.050f5911e,68f1c7747,b617576af,62d80787b,6bd076c19,a95e122dc) and its upstream revertc7b219364: net zero upstream.98ce8af56,11c4a257c,b0001cb67), perf(agc): share snapshot copies and the BDA table of repeated address-based builds boykopovar/AnyPS5#5542 (619be6979,97c3687b0), sync: small HLE libraries from upstream (VideoOut labels, ajm m4aac, ngs2, pad rumble, ime, tools) #494 (58b6ddf72,94ea410c9) and perf(agc): refresh pure data words of a cached draw stage instead of recapturing it boykopovar/AnyPS5#6093 (56bb6377d): these change no code the Metal driver compiles.Recorder,ShaderResources,GuestBufferMemory,DrawCacheandVulkanDeviceare outside the rosetta build's sources, and their header hunks only add VulkanDriver/Recordermembers. Per slice scope, their Vulkan-only hunks are dropped.af7ca4af5(PS_ITER_SAMPLE),b6cde5698(per-pixel sample locations),4b71846fa,6e6334e7e,84f636494(MultisampleTarget sampling),9394a6f51,8c7669334,02974ea76,a15f16324(FMASK decompress),d0cd50c82,03e6cbf43,f093cf497(undrawn MSAA texture),1ffc5f672(per-pixel coverage masks; it needsState::samplesand a host sample mask the Metal draw path does not set),620676bf9,a17f25b5a(Vulkan CB resolve).77521f7ad,789b7f853,b41bf66ca,90be83b71,d87c6d13e,5a8623a13,aec7064af,b0c7cef61,92f0d1ad6,97a0a4d09,b82e0c939,ce83818dc,383c8a651, and the shader-slice cache-format commits46a6f26f5,d8e97a769. This is a workaround for Vulkan devices withoutVK_EXT_shader_stencil_export. Metal writes the stencil reference natively, and its draw path has no replay, so the cache format stays at 37.5fd9c80fa(shader slice, serializer replays at upstream v29) follows1ffc5f672.d9e47d1e9,34525fdf7,c794273ab,55eefe9c5. The recompiler would emit descriptor tables that the Metal backend has no binding path for.dd7d649c3,62eff52c4,a5904f437,f8aa9046d,6b480cc2b,ad5073432,86c66916a,a84afe931,b3e5acc8c,03b7cb5a1,ededc2eb6,7b68d3fb4,2fb034049,7b200acd7,7d898ae1a,2cf6b09fe.PerformanceTrace):1effd67b7,a53332472.f37b02efc: the fork's olderfillBuffer, without memory-value fills or the MSAA fill absorb71fd1c0e5: watched-import window copy (perf(agc): compare an import window's pages when the window closes boykopovar/AnyPS5#3874)8fec47a4b: per-slice HTILE. It needs the upstream plane owners and memory-value fills, and the sharedState.cpphunk alone would break the Vulkan clear match. Metal does not read HTILE.18522aeab: prioritized preparation queue69702ef10,260514de7: unwatch/layerOriginal1ce75da69:CompletePendingCpuWrites7fae4549e,ae5309e1c,da47083cc,8c8cd86cf,7aae95733: upstreamcomputePipelinehelper andPipelineCacheSynchronizationea3a2152d: write-back across adjacent ranges, with 7 conflicting hunks404075b0a: UntrackedHint snapshot keysc22bda1d8(unsupported request version 28 test): upstream numbering. The fork's marker follows fork version 26 (now 27 = unsupported).Fork commits
3dc0eea15fix(agc): take the stages in the Metal shader preparation stub (MetalHostExports.cpp, forced by11ef8e6c8).e50cf0545test(agc): the Metal render-state early-depth fixture sets fullPA_SC_AA_MASK.72518f64freads those registers inDecodePixelStageInfo, soanyps5_metal_render_statethrew "missing register at DWORD 0x30e" without them.Evidence
Rosetta x86_64 (
agent_build.sh rosetta,-DANYPS5_ROSETTA_LIBS=ON,BUILD_TESTING=ON):rosetta_libs rosetta_engine anyps5_agc_replay libSceAgcDriver metal_utility_testsbuilt. ctestmetal_utility_testspassed.rosetta_direct_graphics_testsdoes not compile (ShaderMemory.hpp:4includesRecompiler.hpp, which is not on the target's include path). Main has the same include and the sameRosettaGraphics.cmake/test sources, so this is pre-existing and not from this slice.build-rosettais kept, so the coordinator can replay withbuild-rosetta/rosetta/bin/anyps5_agc_replay.arm64 guest replay (
agent_build.sh guest-replay): full build, then ctest withoutanyps5_metal_presentation_replay: 59/59 passed after fork commite50cf0545(58/59 before it).request_serializer_tests(core/shader/recompiler/tests/RequestSerializerTests.cppwithRequestSerializer.cpp, built standalone with clang++ arm64): passed at fork version 26.New execution tests on the Metal device shim:
QuadPixelMaskandStreamCopywere tried intests/metal_semantics/registration.cmake. They needVulkanDevicegraphics members (PixelPushLayout,CompiledShader) or Vulkan fill HLE that the shim lacks, so they are not registered.Vulkan-device targets and the new
tests/execution/*files are carried but not compiled or run on macOS.After the rebase onto main (
2c3ff5018), rosetta (rosetta_libs rosetta_engine anyps5_agc_replay libSceAgcDriver metal_utility_tests) and the full guest-replay config were rebuilt. Guest-replay ctest passed 59/59 withoutanyps5_metal_presentation_replay, andmetal_utility_testspassed 1/1.AGC frame replay (x86_64
anyps5_agc_replay). The baseline is main after Upstream sync 11D: shader recompiler (13 commits) #511, whose tree equals this branch's base:--expect-hash 5e5670079f1ae58a(--repeat 4)--expect-png replay-ref.png --max-diff-pixels 8(--repeat 3)Not run: game smokes.
No performance claims; nothing was measured for speed.
Review findings (chatgpt-codex-connector)
Reviewed at
e50cf05, the pre-rebase tip with the same tree. No review of the rebased head arrived within 15 minutes.core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvMemoryInstructions.cpp:1291ds_ordered_countwhose first active lane is in the upper half shuffles its amount from the lower half🤖 Generated with Claude Code
https://claude.ai/code/session_01DgW4n3qYgi5jAAohEmXRQj